package org.NooLab.glue.filter;

import org.NooLab.glue.MessageBoard;
import org.NooLab.glue.components.ClientMatcherIntf;
import org.NooLab.glue.components.GlobalReceipts;
import org.NooLab.glue.components.Message;
import org.NooLab.glue.components.MessageBoardFactoryProperties;
import org.NooLab.glue.components.SenderWrap;
import org.NooLab.glue.msgframe.MetaRegistration;
import org.NooLab.glue.msgframe.XMessage;
import org.NooLab.glue.msgframe.XRegistration;
import org.NooLab.glue.net.ComBoxFactory;
import org.NooLab.glue.net.ComBoxIntf;
import org.NooLab.glue.net.HostingData;
import org.NooLab.glue.net.HostingDataItem;
import org.NooLab.glue.net.env.ConnectionsManager;
import org.NooLab.glue.storage.MsgBoardDataStorage;
import org.NooLab.glue.subscription.FilterPackageIntf;
// import org.NooLab.glue.storage.persistence.PersistenceHandling;
import org.NooLab.glue.transaction.Transactions;
import org.NooLab.utilities.logging.PrintLog;
 
 

public class RegisterMessageInterpreter {

	MessageBoard messageBoard; 
	
	GlobalReceipts globalReceipts;
	
	MetaRegistration metaRegistration;
	
	ComBoxIntf comBox;
	// ComBoxFactory comBoxFactory;
	
	Transactions transactions;
	MsgBoardDataStorage msgBoardStorage;
	XRegistration xRegistration ; 
	
	ConnectionsManager connectionsMgr;
	
	MessageBoardFactoryProperties  factoryProperties;
	
	FilterPackageIntf filterPackage;
	
	ClientMatcherIntf clientMatcher;
	
	String originatorID="" ;
	
	PrintLog out;
	
	
	public RegisterMessageInterpreter( MessageBoard messageboard, 
			   						   PrintLog outprn){
		
		this.messageBoard = messageboard;
		
		globalReceipts = messageBoard.getGlobalReceipts();

		metaRegistration = messageBoard.getMetaRegistration() ; // contains the collection "registeredInstances"
		
		factoryProperties = messageBoard.getMsgBoardShares().getMsgBoardFactory().getFactoryProperties() ;
		
		comBox = messageBoard.getComBox() ;

		// comBoxFactory = messageBoard.getComBoxFactory();
			
		msgBoardStorage = messageBoard.getMsgBoardStorage() ;
		
		transactions = messageBoard.getTransactions() ;
		
		clientMatcher = messageBoard.getClientMatcher() ;
		 
		connectionsMgr = messageBoard.getConnectionsMgr();
		
		if (clientMatcher!=null){
			clientMatcher.setMessageBoard(messageBoard) ;
		}
		
		
		out = outprn;
		 
	}
	
	
	
	
	public int interpretingSingleRegMessage( Message msg){
		
		int result= -1;
		String rawXmlMsg  ;
		 
		 
		
		 
		
		rawXmlMsg = msg.rawXmlMsg ;
		
		// the classed thread ("SourceHandler") will take it in FiFo style and 
		// route it one by one to interpreteSourceMsg)=
if (rawXmlMsg.contains("unregister") ){		
	// out.printErr(1,"\n-------------------"+rawXmlMsg+"\r\n-------------------") ;		
}		
		
	
		result = handlingSingleRequestForRegistering(rawXmlMsg, msg.getGUID() );
 
		// now it will be taken acc. to FiFo by the "SourceHandler{}"
		
		if (rawXmlMsg.length() > 40){
	
		}
		
		return result;
	}
	
	
	/**
	 * 
	 * xReg is a pseudo-object, created upon the unregister message, just for transporting basic info  
	 * @param xReg
	 */
	public void removeRegisteredInstance( XRegistration xReg){
		XRegistration xmetareg;
		int p=-1,sv;
		long iid;
		
		out.print(3, "removing registered Instance() ..." );
				
		for (int i=0;i<metaRegistration.size();i++){
			
			xmetareg = metaRegistration.getItem(i) ;
			iid = xmetareg.getInstanceID();
			sv = xReg.getReceptorState();
			if (iid == xReg.getInstanceID()){
				
				if ((sv!=XRegistration.RST_IS_TIMEDOUT) || 
				   ( (sv>=XRegistration.RST_IS_STARTED) && (sv<XRegistration.RST_IS_RUNNING))){
					p = i;
					break;
				}
			}
			
		}// i->
		
		if (p>=0){
			xmetareg = metaRegistration.getItem(p) ;
			
			messageBoard.removeRegistration( xmetareg ,p ) ;
		}
		
	}




	/**
	 * 
	 * In case of http (which is asynchronous, and not constantly connected)  we have a problem:
	 * if a participant has been already registered, but the message did not arrive over there, the participant
	 * probably tries again to register; 
	 * thus we have to check whether we already know him, then not doing further registration ?
	 * But what if the wires TO the participant are faulty?
	 * 
	 * It depends on the time distance between trials... if there are more than 10 seconds between the attempts
	 * then we deny it... and send a shutdown command back to the participant through the connection...
	 * THIS ONLY for http !!!!
	 * 
	 *  
	 * 
	 * @param rawXmlMsg
	 * @param thrdGUID
	 * @return
	 */
	synchronized protected int handlingSingleRequestForRegistering( String rawXmlMsg, String thrdGUID ){
		/*
		   <register>
	  		  <name value="test-source-0"/>
	  		  <port value="50001"/>
		   </register>
		*/
		int result = -1;
		long instanceID = -1;
		String   path="" ;
		int    z,   transport ;
		long rid = -1 ;
		 
		XMessage xmsg ;
		String[] rawIndicators ;
		
		//PersistenceHandling persistenceHandler ;
		
		 
		
		try{
			
												out.print(5, "basic raw xml requesting registration response : \n\r"+rawXmlMsg);
			xmsg = new XMessage(out) ;
			
			  
			z = rawXmlMsg.indexOf( "<unregister" );
			if (z>0){
				handlingUnRegistration(rawXmlMsg);
				System.gc();
				return 0;
			}
			
			z = rawXmlMsg.indexOf( "<check " );
			if (z>0){
				handlingConnectionCheckResponse(rawXmlMsg) ;
				System.gc();
				return 0;
			}

			 
			
			if (messageBoard.getProtocolID() >= MessageBoardFactoryProperties.protocolTCP ){
				rawXmlMsg = xmsg.removeMessageBoardRoutingMetaTag(rawXmlMsg);
			}
	
														out.print(3, "\nhandling Request for registering, thread GUID : "+thrdGUID+" ... ");
			// -------------------------------------------------------------------------------------------------------------------------------------- 
		
			z=0;
			originatorID = xmsg.getInfoFromProlog(rawXmlMsg,"origin","id",".");
			
														if (originatorID.length()>0){
															out.print(4, "Originator detected : "+originatorID) ;
														}
			rawXmlMsg = xmsg.removePrologFromXml(rawXmlMsg) ;

			
			
			if (originatorID.length()==0){
				if (rawXmlMsg.indexOf("<origin id")>=0){
					path = "//origin";
				}
				if (rawXmlMsg.indexOf("<originator id")>=0){
					path = "//originator";
				}
				if (path.length()>0){
					originatorID = xmsg.getSpecifiedInfo(rawXmlMsg, path, "id") ;
				}
			}
			 
			xRegistration = xmsg.readRegistrationRequest( rawXmlMsg ) ;
			
			if ((int)((Integer)metaRegistration.iidIsRegisteredOrReserved(xRegistration.getInstanceID() , 1))>0){
				//  for requested uniques not here... just let it run through, it will be 
				//  handled in digestingInitialRegistration:: returnRegistrationDeny
				// for not uniques, just repeat,  the MessageBoard will assign a new id next time
				if (xRegistration.getInstanceIsUnique()==false){
					return 0;
				}
			}
			
			// if we have registMode_LASTWINS, the current one will be removed.. which could result 
			// in a mess of alternating applications, thus it should be used only if there is NO remote machine
			checkRegisteredInstancesForZombies( xRegistration ) ;
			 
			
			// the returned registration will comprise an activated connection delay (and overrule
			// the full-duplex request of the participant), if the message board itself is in half-duplex mode
			// due to the respective transport protocol
			transport = comBox.getActiveTransportId() ; 
			
			if ( ( ( transport <= ComBoxFactory.DRS_FTP ) || (  messageBoard.getFullDuplexConnection()<=0)) &&  
				 (xRegistration.getConnectionDelay()<=0.0)){
				xRegistration.setConnectionDelay(MessageBoard.connectionDelayDefault) ; 
				
			}
			
			if ((xRegistration.getInstanceID()<0) ){
				 
				rid = metaRegistration.getRegisteredIDSafely();
				xRegistration.setInstanceID( rid ) ;// globalReceipts.getGlobalRegisteredID()
				
 			}
			
			instanceID = xRegistration.getInstanceID();
		
			
			
			
			rawIndicators = new String[]{"<register>","<instance","<content type=","<port value="} ;
			if (digestingInitialRegistration( xmsg, rawXmlMsg ,rawIndicators) ){ return result; }
			
			 
			rawIndicators = new String[]{"<register>","<ping", "keepalive","<system>"} ;
			if (handlingRefreshMessage( xmsg, rawXmlMsg ,rawIndicators) ){ return result; }
			
			result = 0;
		}catch(Exception e){
			e.printStackTrace();
			result = -1;
		}
		 
		
		 
		if (result<0){
			if (instanceID>0){
				metaRegistration.removeItemByID(instanceID);
			}
		}else{
			messageBoard.showResultingSummary( instanceID , result) ;
		}

		return result;
	}
	


	
	private synchronized boolean digestingInitialRegistration(XMessage xmsg, String rawXmlMsg, String[] rawIndicators ) {
	/*
		<messageboard name="spela" role="SOURCE">  ... -> or role="IBOARD"
   		 	<register>
        		 <name value="testSource0-source-2-ed2cab0b-8089-4ca6-aaf6-0b1ce607e55f"/>
        		 <instance id="2528"/>
          		 <port value="7070"/>
          		 <listenport value="-1"/>
          		 <content type="doc,*"/>
          		 <connectionDelay value="-1.0"/>
          		 <unique value="1"/>
          		 <linkrelation value="2"/>
          		 <relationitemid value="-1"/>
          		 <relationgroupid value="-1"/>
       	   </register>    		     		 
    	   <originator id="BaseResource$MessageSupply@9f3e95"/>
    	</messageboard> 
	*/

		boolean result=false,hb = false,names_are_equal ;
		String str, applicantsName, providedName, regname;
		String applicantsAddressListStr="";
		
		int activeport = 0,listenport,uniqueReqrest,ix,p,suggix;
		long iid, siid;
		XRegistration xxreg=null ;
		
		
		result = rawIndicatorsCheck( rawXmlMsg, rawIndicators);
		
		if ( result ){
			
			xmsg.setContentRoot("register");
			
// check first contact, which often returns "" !!!			
		    // xRegistration is the xreg object as defined by the xml request
			str = xRegistration.getRole().toLowerCase().trim() ;
			// if (str.contains("source")){ 
			if (MessageBoardFactoryProperties.isSourceType(str)){
				activeport = messageBoard.getMsgPortforSources();
			} 
			if (str.contains("receptor")){
				activeport = messageBoard.getMsgPortforReceptors() ;
			}
			
			listenport = (int)xmsg.getSpecifiedValue(rawXmlMsg, "/listenport", "value");
			applicantsName = xmsg.getSpecifiedInfo(rawXmlMsg, "/name", "value");
			
			iid = xRegistration.getInstanceID();
			
			if (activeport >= 0) {
				
		 		if (iid<=0){
		 			iid = xmsg.getSpecifiedValue(rawXmlMsg, "instance","id"); // getinstanceID( rawXmlMsg, "instance") ;
		 		}
				// Vector<XRegistration>  metaRegistration.getRegisteredInstances()
				// xxreg = messageBoard.retrieveRegistrationObject(iid) ;
				
		 		// we also have to know the address of the applicant ?
		 		// then the MessageBoard could refer to a second-line persistence, and suggest 
		 		// dedicated IDs to instances on a particular machine : applicants addresses -> collection of IDs
		 	
				applicantsAddressListStr = xmsg.getSpecifiedInfo(rawXmlMsg, "//machine/address", "list");
				
				str = xmsg.listContainsAny( applicantsAddressListStr, messageBoard.getIpAddressListStr() );
		 		if (str.length()>0){
		 			// TODO: now we know, that the applicant is on the MessageBoard's machine, too !!!
		 			
		 		}
		 		
				uniqueReqrest = (int)xmsg.getSpecifiedValue(rawXmlMsg, "//unique", "value");
				
				providedName = xmsg.getSpecifiedInfo(rawXmlMsg, "//name", "value") ;
				
				// the new registration should NOT use an ID that is identical to any other already registered 
				ix = checkRegisteredInstancesForUniqueIds( xRegistration ) ;
				suggix = -1;
				// and it also should NOT be contained in reserved IDs, unless this registrations NAME
				// is already known to the MessageBoard (due to a previous attempt, and suggested ID)
				p = metaRegistration.getReservedIDs().indexOf(iid);
				 
				if (p>=0){
					regname = (String)metaRegistration.iidIsRegisteredOrReserved(iid, 2) ;
					// 
					if (regname.length()>0){
						siid = metaRegistration.getReservedIDs().get(p) ;
						suggix = p;
					}
				}
				
				if ((ix<0) && (p>=0) && (suggix<0)){
					long rid = metaRegistration.getReservedIDs().get(p) ;
					if (rid>0){
						// messageBoard.getr
						ix = metaRegistration.indexOf(rid) ;
					}
				}
				
				if (ix>=0){
					xxreg = metaRegistration.getItem(ix) ;
					 // if there is already one of the same ID, and we have registMode_FIRSTWINS, then
					 // we deny registration -> create a message
				}
				 
				names_are_equal = (xxreg!=null) && (xxreg.getNameOfApplicant().contentEquals(providedName)==true);
				
				/*
				 * problem 1: after a failing xreg, the xxreg != nulll, i.e. the meta reg does not get cleaned
				 *  
				 */
				
				if ( ((xxreg!=null) && (names_are_equal==false) && (uniqueReqrest>=1)  ) ||
				     ( (xxreg!=null) && (names_are_equal==true) && (uniqueReqrest>=1) ) ){
					/* now we can not respect the request for uniqueness
					 * we create a message for reply, but do NOT register here!
					 * it is upon the applicant whether to proceed with a different id 
					 */
					out.printErr(2, "request for unique registration can't be satisfied!");
					
					if ( messageBoard.getModeForConflictingIDs()== MessageBoardFactoryProperties.registMode_LASTWINS){
						hb = true;
					}
					if ( messageBoard.getModeForConflictingIDs()== MessageBoardFactoryProperties.registMode_FIRSTWINS){
						hb = false;
					}
					if (hb==false){
						// of course, we should not remove the failing iid, since this attempt failed 
						// exactly because that iid is already existing...
						
						 //TODO
						 
						activeport = listenport; // is NOT the port for standard xml exchange, but must be the regconfirmport
						activeport = xRegistration.getPort();
						
						returnRegistrationDeny( xmsg, iid, activeport ,applicantsName, "id"); 
						// role is missing in xml !
						
						// from index ix we retrieved xxreg, which is the competing instance
						// metaRegistration.removeItem(ix);
						xxreg = null;
						xRegistration = null ; 
						// clear meta, !!
						return result;
					}
					
				} 
				
				int r = provideRegistrationData( xmsg, xRegistration, activeport);
					
				// saving address + ID + Name
				if (r==0){
					storeHostingData( applicantsAddressListStr, providedName, iid);
				}
				
			}
			
			
			
		}
		
		return result ;
	}
	
	private void storeHostingData( String addresses, String applicantsName, long iid){
		
		HostingDataItem hostingDataItem ;
		HostingData hdata;
		
		if ((addresses.length()<8) || (applicantsName.length()==0) || (iid<=0) ){
			return;
		}
		
		hostingDataItem = new HostingDataItem( addresses, applicantsName, iid);
		  
		hdata = messageBoard.getHostingData() ;
		
		hdata.add(hostingDataItem) ; 

		msgBoardStorage.storeHostingData( hdata, messageBoard.getMBid() ); 
	}
	
	
	private boolean handlingRefreshMessage( XMessage xmsg, String rawXmlMsg, String[] rawIndicators ) {

		boolean result=false ;
		 
		long iid;
		XRegistration xreg ;
		
		
		result = rawIndicatorsCheck( rawXmlMsg, rawIndicators);
		
		if ( result ){
			
			iid = xmsg.getSpecifiedValue(rawXmlMsg, "//register/instance","id"); // getinstanceID( rawXmlMsg, "instance") ;
			if (iid<0){
				out.print(2,"handlingRefreshMessage(), refreshing the registration for client  \n"+ rawXmlMsg);
				iid = xmsg.getSpecifiedValue(rawXmlMsg, "//instance","id"); 
			}
			// Vector<XRegistration>  metaRegistration.getRegisteredInstances()
			xreg = messageBoard.retrieveRegistrationObject(iid) ;
			
												out.print(2, "refreshing the registration for client id="+iid);
			if (xreg!=null){
				xreg.setRegisteredSince( System.currentTimeMillis() ) ;
			}else{
												out.printErr(2, "... failed!");
			}
		}
	
		return result ;	
	}
	
	protected void handlingConnectionCheckResponse( String rawXmlMsg){
		
		String responseStr ;
		XMessage xmsg ;
		
		xmsg = new XMessage(out) ;
		
		responseStr = xmsg.readRegistrationsConnectionCheck( rawXmlMsg );
		// is sth like <iid>::<GUID>
		
		connectionsMgr.importCheckfor( responseStr );
	
	}

	/**
	 * 
	 * a source as well as a receptor may wish to disappear from the board
	 * 
	 * 
	 * 
	 */
	private void handlingUnRegistration( String rawXmlMsg){
	  
		XRegistration xRegistration ; 
		XMessage xmsg ;
		 
		xmsg = new XMessage(out) ;
		
		
		xRegistration = xmsg.readUnRegistration( rawXmlMsg ) ;
		
		// regId = xRegistration.getInstanceID() ;
		
		removeRegisteredInstance( xRegistration ) ;
		
	}
	
	private void returnRegistrationDeny( XMessage  xmsg, long instanceID, int listenport, String name, String reason){
		
		String xstr, suggestion="";
		Long suggID;
	
		
		             
		/*
		 * we also have to save the suggested ID together with the name (needs to be a unique(d) name),
		 * such that, if the instance returns with the suggested ID we recognize it and can assign it,
		 * but at the same time no other client would get that ID
		 */
		suggID = metaRegistration.getSuggestionForID(name);

		if (suggID>0){
			
		}
		
		suggestion = ""+suggID;
		
		xstr = xmsg.createRegistrationDenialReply( instanceID, name, reason, suggestion);
		
													out.print(3, "preparing response message about denial of registration, \r\n"+
																 "reason was: "+reason+" ,  suggested ID is: "+suggestion) ;
													
		xstr = xmsg.insertRawToXml( originatorID, "originator","id", xstr, "</messageboard>",1); 
		
		messageBoard.syncedSend( listenport, xstr );
		// SenderWrap sender = new SenderWrap(comBox);
		// sender.sendingMessage(xstr, listenport);
		// has a callback observer  MessageBoard()" !!
	}



	private int provideRegistrationData( XMessage  xmsg, XRegistration xRegistration, int activeport){
		
		int result = -1;
		long instanceID;
		int cport , sendModeOfBoard,  regConfirmPort;
		boolean vport ;
		String xstr ;
		
		instanceID = xRegistration.getInstanceID();
		
		xRegistration.setActiveport( activeport ) ;
		 
		cport = xRegistration.getClientListeningPort();
		
		cport = messageBoard.ensureUniqueListeningPortForParticipant(cport) ;
		
		xRegistration.setClientListeningPort(cport) ;
		
		vport = messageBoard.isVirtualPorts() ;
		xRegistration.setVirtualPorts( vport ) ;
		if ((vport) || (messageBoard.getProtocolID() <= MessageBoardFactoryProperties.protocolFTP)){
			xRegistration.setMsgPortAllInOne( messageBoard.getMsgPortAllInOne() ) ;	
		}
		
			   sendModeOfBoard = messageBoard.getSendModeForBoard() ;
		xstr = xmsg.createRegistrationReply( xRegistration,sendModeOfBoard );
		
		// we could have two different transport protocols !!!!
		// so we should not test for the protocol of the primary protocol (always http in the case of dual), but
		// we have to use the protocolID as it is indicated by the xRegistration instance itself
		
		// boolean hb = messageBoard.transportProtocolIsMatching( xRegistration );
		if ((originatorID.length()==0) && (messageBoard.getProtocolID() == MessageBoardFactoryProperties.protocolHREST)){
			out.printErr(2, "Critical Problem in <handlingSingleRequestForRegistering()>: originator-id is not indicated as expected, originator id="+originatorID);
		}
		// nothing will be added if the originatorID == "" in case of non-http-rest !!
		xstr = xmsg.insertRawToXml( originatorID, "originator","id", xstr, "</messageboard>",1); 
	
		// send it back
	 						
		regConfirmPort = xRegistration.getPort() ;
		
		// it is very important, that the instances of the 
		// sender are LOCALly defined == inside separate threads, 
		// otherwise there will be collisions through overlaps
		
		result = -3;
		messageBoard.syncedSend( regConfirmPort, xstr );
		// this sender uses the factoryMode: if it is 3 then it behaves as a board, i.e. it returns
		// the response within session (before timeout)

	
		if ( (instanceID>0)){
			result = -5;
			
			xRegistration.setReceptorState( XRegistration.RST_IS_STARTED );
												out.print(3, "registration object (id:"+xRegistration.getInstanceID()+") added to collection...");
			metaRegistration.getRegisteredInstances().add(xRegistration ); // <<<<<<<<<<<<<<<<<<<<<<<<
			
			msgBoardStorage.saveMsgBoardData() ;
			
			// this will start its own threaded process, but will return only if its state 
			// can be definitely concluded (after a timeout of several seconds
			messageBoard.setRegistrationToTested(instanceID,true); // see ConnectionManager
			
			result = -7;
			// reginiPort = xRegistration.getPort();
			// messageBoard.getComBox().getFactory().
			xRegistration.setPort(-1);
			
			
			if (MessageBoardFactoryProperties.isSourceType(xRegistration.getRole())){
				// persistenceHandler = new PersistenceHandling(mb);
				// persistenceHandler.checkForHibernatedResults();
			}
		}
		
		if (xRegistration.getInstanceConnectionConfirmed() ){
			result=0;
		}
		return result;
	}




	private boolean rawIndicatorsCheck( String rawXmlMsg, String[] rawIndicators){
		boolean rB=false;
		int isum=0;
		
		int[] p = new int[rawIndicators.length] ;
		
		for (int i=0;i<rawIndicators.length;i++){
			p[i] = rawXmlMsg.indexOf( rawIndicators[i]);
			
			if (p[i]>=0){
				isum = isum+ 1;
			}
		}
		
		rB = (isum == p.length) ;
		
		return rB;
	}


	
	private int checkRegisteredInstancesForUniqueIds( XRegistration xregNew ){
		int resultIx = -1;
		boolean rB=false;
		XRegistration xreg ;
		int i;
		

		i=0;
		while (i<metaRegistration.size()){
			
			
			xreg = metaRegistration.getItem(i) ;
			
			if (xreg.getInstanceID() == xregNew.getInstanceID()){
				
				// ??? which property xreg.
				if ( messageBoard.getModeForConflictingIDs()== MessageBoardFactoryProperties.registMode_LASTWINS){
					
				}
				if ( messageBoard.getModeForConflictingIDs()== MessageBoardFactoryProperties.registMode_FIRSTWINS){
					
				}
				if ( messageBoard.getModeForConflictingIDs()== MessageBoardFactoryProperties.registMode_FREQWINS){
					
				}
				rB=true;
				resultIx = i;
				break;
			}
			
			i++;
		} // i->0
		
		
		
		return resultIx;
	}

	private void checkRegisteredInstancesForZombies( XRegistration xregNew){
		
		boolean isLeftOver;
		XRegistration xreg ;
		int i;
		
		// zombies may have the same instanceID OR the same name
		
		i=metaRegistration.size()-1;
		while (i>=0){
			isLeftOver = false;
			
			xreg = metaRegistration.getItem(i) ;
			
			if (xreg.getInstanceID() == xregNew.getInstanceID()){
				isLeftOver = true;
			}
			if (isLeftOver==false){

				if (xreg.getNameOfApplicant().contentEquals( xregNew.getNameOfApplicant())){
					isLeftOver = true;
				}

			}
			// it is not necessarily a leftover... if participants on different machines use 
			// the same ID we encounter a conflict
			if ((isLeftOver) && ( messageBoard.getModeForConflictingIDs()== MessageBoardFactoryProperties.registMode_LASTWINS)){
				metaRegistration.removeItem(i) ;
			}
			i--;
		} // i->0
		
	}

}
